#!/usr/bin/env python
# encoding: utf-8
# @author: Lin Han
# @contact: voldemort22@126.com
# @file: deprecated_app.py
# @time: 2021/3/23 18:48
# @desc:
import json

import requests
from fastapi import APIRouter, File, UploadFile, Request

from application.parameter_model.crud import generate_parameter_model_data
from application.parameter_model.queryModels import ParameterModelChangeSize, UploadParameterModel
from cache.redis_pool import get_redis
from models.queryModels import UpdateParamConfigData, MultipleConditionQueryParameterModels, LockFlagQuery, UpdateParamModelProperty
from models.responseModels import ResponseBool, ResponseDict, ResponseStr
from utils.mongo_tools import retrieve_all_mongo_values, update_mongo_value, delete_mongo_value, create_one_mongo_value, retrieve_one_mongo_value, parameter_model_number_generator
from utils.utils import create_folder, write_file
from views.configs import *
from views.crud import upload_to_aliyun_parameter_model, keyword_search_parameter, separate_page, send_to_message_queue

parameter_model_router = APIRouter(
    prefix="/api/parameter_model",
    tags=["parameter_model"],
)


@parameter_model_router.post("/v1/parameter_models")
def multiple_condition_query_parameter_models(queryModel: MultipleConditionQueryParameterModels):
    """
    获取 所有符合条件的 参数化模型的数据
    如果redis里用202105开头的正则匹配不到一条数据，那就去mongo数据库里取所有的参数化模型数据，把它们存到redis里。

    - :param queryModel:
    - :return:
    """
    redis_connection = get_redis(port=PARAMETER_MODEL_REDIS_PORT)
    model = {"data": {"result": []}}
    result = []
    parameter_model_number_list = redis_connection.get("parameter")
    parameter_model_number_list = json.loads(parameter_model_number_list)
    if len(parameter_model_number_list) > 0:
        for i in parameter_model_number_list:
            temp_item = redis_connection.get(i)
            temp_item = json.loads(temp_item)
            result.append(temp_item)
    else:
        result = retrieve_all_mongo_values(
            {},
            collection_name=PARAMETER_MODEL_COLLECTION
        )
        for i in result:
            redis_connection.set(i["number"], json.dumps(i))

    result = keyword_search_parameter(queryModel, result)
    model["data"]["total"] = len(result)
    if len(result) > 0:
        # 如果isTotal为True，意味着进入了详情页面，则不需要分页了。
        if not queryModel.isTotal:
            model["data"]["result"] = separate_page(result, page=queryModel.page, pagesize=queryModel.pagesize)
        else:
            model["data"]["result"] = result
    model["status"] = 1
    return model


# TODO: 20210615写到这里。
@parameter_model_router.put("/v1/parameter_model_flag_tag", response_model=ResponseBool)
async def update_parameter_model_flag_tag(request: Request, queryModel: LockFlagQuery):
    """
    设置 参数化模型 标签锁定 isFlag = True

    - :param oneInfo:
    - :return:
    """
    updateInfo = {"$set": {"isFlag": queryModel.isFlag}}
    update_mongo_value(
        {"number": queryModel.number},
        updateInfo,
        database_name=MONGO_DATABASE_NAME,
        collection_name=PARAMETER_MODEL_COLLECTION
    )

    try:
        original_data = retrieve_one_mongo_value(queryModel.number, database_name=MONGO_DATABASE_NAME, collection_name=PARAMETER_MODEL_COLLECTION)[0]
        await request.app.state.redis.set(queryModel.number, json.dumps(original_data))
    except:
        pass

    model = {"data": True, "status": 1}
    return model


@parameter_model_router.delete("/v1/parameter_model")
async def delete_parameter_model(request: Request, number: str):
    """
    删除 一个 参数化模型 字段
    - :param number:
    - :return:
    """
    try:
        await request.app.state.redis.delete(number)
    except:
        pass
    delete_mongo_value(
        number=number,
        database_name=MONGO_DATABASE_NAME,
        collection_name=PARAMETER_MODEL_COLLECTION
    )
    model = {"data": True, "status": 1}
    return model


@parameter_model_router.put("/v1/parameter_model", response_model=ResponseBool)
async def update_parameter_model(request: Request, queryModel: UpdateParamModelProperty):
    """
    参数化模型 详情页更新

    - :param queryModel:
    - :return:
    """
    tag = retrieve_all_mongo_values(
        {"number": queryModel.number},
        database_name=MONGO_DATABASE_NAME,
        collection_name=PARAMETER_MODEL_COLLECTION,
    )[0]['tag']
    if queryModel.standard is not None:
        tag['standard'] = queryModel.standard
    if queryModel.category is not None:
        tag['category'] = queryModel.category
    if queryModel.partType is not None:
        tag['partType'] = queryModel.partType
    if queryModel.elseTag is not None:
        tag['elseTag'] = queryModel.elseTag
    updateInfo = {"$set": {"tag": tag}}
    update_mongo_value(
        {"number": queryModel.number},
        updateInfo,
        database_name=MONGO_DATABASE_NAME,
        collection_name=PARAMETER_MODEL_COLLECTION
    )

    try:
        original_data = retrieve_one_mongo_value(queryModel.number, database_name=MONGO_DATABASE_NAME, collection_name=PARAMETER_MODEL_COLLECTION)[0]
        await request.app.state.redis.set(queryModel.number, json.dumps(original_data))
    except:
        pass
    model = {"data": True, "status": 1}
    return model


@parameter_model_router.get("/v1/parameter_model")
async def retrieve_history_part(request: Request, number: str):
    """
    返回一条参数化模型的完整信息

    - :param number: 编号
    - :return:
    """
    model = {"data": {}}

    try:
        parameter_model = await request.app.state.redis.get(number)
        original_data = json.loads(parameter_model)
        print(original_data)
    except:
        # if reach here then means no data in redis. Now go to mongo.
        original_data = retrieve_one_mongo_value(number, database_name=MONGO_DATABASE_NAME, collection_name=PARAMETER_MODEL_COLLECTION)[0]
        # then add it into redis
        await request.app.state.redis.set(number, json.dumps(original_data))

    try:
        model["data"] = original_data
        model["status"] = 1
    except:
        model["status"] = 0
    return model


@parameter_model_router.put("/v1/parameter_model_config", response_model=ResponseBool)
async def update_parameter_model_config(request: Request, oneInfo: UpdateParamConfigData):
    """
    这个是更新config表的，不是更新数据表格，别和parameter_model的url混了。

    - :param oneInfo:
    - :return:
    """
    configData = retrieve_all_mongo_values(
        {"type": "standardPart"},
        database_name=MONGO_DATABASE_NAME,
        collection_name="config",
    )[0]['configData']
    if oneInfo.standard is not None:
        configData['standard'] = oneInfo.standard
    if oneInfo.makeType is not None:
        configData['makeType'] = oneInfo.makeType
    if oneInfo.partType is not None:
        configData['partType'] = oneInfo.partType
    updateInfo = {"$set": {"configData": configData}}
    update_mongo_value(
        {"type": "standardPart"},
        updateInfo,
        database_name=MONGO_DATABASE_NAME,
        collection_name="config",
    )

    await request.app.state.redis.set("parameter_model_config", json.dumps(configData))

    model = {"data": True, "status": 1}
    return model


@parameter_model_router.get("/v1/parameter_model_config", response_model=ResponseDict)
async def get_parameter_model_values(request: Request):
    """
    获取 参数化模型 所需要的配置信息
    - :return:
    """
    try:
        configData = await request.app.state.redis.get("parameter_model_config")
        configData = json.loads(configData)
    except:
        configData = retrieve_all_mongo_values(
            {"type": "standardPart"},
            database_name=MONGO_DATABASE_NAME,
            collection_name="config"
        )[0]['configData']
        # 把mongo中查到的数据set到redis数据库中
        await request.app.state.redis.set("parameter_model_config", json.dumps(configData))

    model = {"data": configData, "status": 1}

    return model

    # model = {"data": {}}
    #
    # result = retrieve_mongo_all_values(
    #     {"type": "standardPart"},
    #     database_name=MONGO_DATABASE_NAME,
    #     collection_name="config",
    # )[0]['configData']
    #
    # model["data"] = result
    # model["status"] = 1
    # return model


@parameter_model_router.get("/v1/parameter_model_gltf_file", response_model=ResponseStr)
async def get_parameter_model_gltf_file(number: str):
    """
    Deprecated.
    查询 参数化模型的gltf文件地址，用于显示

    - :param number:
    - :return:
    """
    model = {"data": ""}
    original_data = retrieve_one_mongo_value(
        number,
        database_name=MONGO_DATABASE_NAME,
        collection_name=PARAMETER_MODEL_COLLECTION,
    )
    try:
        model["data"] = original_data[0]["file"][GLTF_OSS_ADDRESS]
        model["status"] = 1
    except:
        model["status"] = 0
    return model


@parameter_model_router.get("/v1/parameter_model_catia_file", response_model=ResponseDict)
async def get_parameter_model_catia_file(number: str):
    """
    Deprecated.
    查询 参数化模型的CATIA文件地址，用于下载

    - :param number:
    - :return:
    """
    model = {"data": ""}
    original_data = retrieve_one_mongo_value(
        number=number,
        database_name=MONGO_DATABASE_NAME,
        collection_name=PARAMETER_MODEL_COLLECTION,
    )
    try:
        model["data"] = {
            "name": original_data[0]['name'],
            "path": original_data[0]["file"][CATPART_OSS_ADDRESS],
        }
    except:
        model["status"] = 0
    model["status"] = 1
    return model


@parameter_model_router.post("/v1/parameter_model_catia_file")
async def upload_parameter_model_catia_file(
        file: UploadFile = File(...),
        desc: str = File(...),
        version: str = File(...),
):
    """
    Deprecated.
    这里接收用户上传的文件，返回上传是否成功，以及上传的文件唯一id（number）。

    - param file: 用户上传的文件
    - param desc: 用户需要添加的描述
    - param version: 参数化模型的版本号
    - return:
    """
    isFeature: bool = False
    isFlag: bool = False
    folder = create_folder()
    file_path = f"{folder}/{file.filename}"
    # 写入文件
    write_file(file_path=file_path, file=file)

    # 上传至阿里云
    parameterModel = upload_to_aliyun_parameter_model(
        file_path,
        desc=desc,
        version=version,
        isFeature=isFeature,
        isFlag=isFlag,
    )
    model = {"data": parameterModel["number"], "status": 1}
    create_one_mongo_value(
        parameterModel,
        database_name=MONGO_DATABASE_NAME,
        collection_name=PARAMETER_MODEL_COLLECTION,
    )
    return model


@parameter_model_router.post("/v2/parameter_model")
async def upload(request: Request, queryModel: UploadParameterModel):
    """
    Deprecated.
    这里接收用户上传的文件，返回上传是否成功，以及上传的文件唯一id（number）。

    - param catpartAliOssAddress: 用户上传的文件路径
    - param desc: 用户需要添加的描述
    - param version: 参数化模型的版本号
    - return:
    """
    number = parameter_model_number_generator()
    parameter_model = generate_parameter_model_data(number, file_path=queryModel.catpartAliOssAddress, desc=queryModel.desc, version=queryModel.version)

    await request.app.state.redis.set(parameter_model["number"], json.dumps(parameter_model))

    create_one_mongo_value(parameter_model, database_name=MONGO_DATABASE_NAME, collection_name=HISTORY_CLAMP_COLLECTION)
    send_to_message_queue(number)

    model = {"data": number, "status": 1}
    return model


# @parameter_model_router.post("/v1/clamp_relation", response_model=ResponseDict)
# async def bind_clamp(queryModel: HistoryClampStandardClamp):
#     """
#     绑定历史夹具和标准夹具的编号
#     - :return:
#     """
#     model = {"data": {}}
#     try:
#         create_one_mongo_value(
#             {
#                 "history_clamp_number": queryModel.history_clamp_number,
#                 "standard_clamp_number": queryModel.standard_clamp_number,
#             },
#             database_name=MONGO_DATABASE_NAME,
#             collection_name="01_03_relation",
#         )
#         model["data"] = {queryModel.history_clamp_number: queryModel.standard_clamp_number}
#         model["status"] = 1
#     except:
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.get("/v1/clamp_relation", response_model=ResponseBool)
# async def retrieve_clamp_relation(history_clamp_number: str, standard_clamp_number: str):
#     """
#     查询历史夹具和标准夹具的关系，若已绑定返回True，否则返回False。
#
#     - :return:
#     """
#     model = {}
#     try:
#         result = retrieve_mongo_all_values(
#             {
#                 "history_clamp_number": history_clamp_number,
#                 "standard_clamp_number": standard_clamp_number,
#             },
#             database_name=MONGO_DATABASE_NAME,
#             collection_name="01_03_relation",
#         )
#         if len(result) > 0:
#             model["data"] = True
#         else:
#             model["data"] = False
#
#         model["status"] = 1
#     except:
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.delete("/v1/clamp_relation", response_model=ResponseDict)
# async def delete_clamp_relation(queryModel: HistoryClampStandardClamp):
#     """
#     取消绑定历史夹具和标准夹具
#     - :return:
#     """
#     model = {}
#     try:
#         model["data"] = {queryModel.history_clamp_number: queryModel.standard_clamp_number}
#         delete_mongo_value_by_filter_condition(
#             {
#                 "history_clamp_number": queryModel.history_clamp_number,
#                 "standard_clamp_number": queryModel.standard_clamp_number,
#             },
#             database_name=MONGO_DATABASE_NAME,
#             collection_name="01_03_relation",
#         )
#         model["msg"] = "success"
#         model["status"] = 1
#     except:
#
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.post("/v1/history_standard_part_relation", response_model=ResponseDict)
# async def bind_history_standard_part(queryModel: HistoryPartStandardPart):
#     """
#     绑定历史零件和标准零件的编号
#     - :return:
#     """
#     model = {}
#     try:
#         create_one_mongo_value(
#             {
#                 "history_part_number": queryModel.history_part_number,
#                 "standard_part_number": queryModel.standard_part_number,
#             },
#             database_name=MONGO_DATABASE_NAME,
#             collection_name="02_04_relation",
#         )
#         model["msg"] = "success"
#         model["status"] = 1
#         model["data"] = {queryModel.history_part_number: queryModel.standard_part_number}
#     except:
#
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.get("/v1/history_standard_part_relation", response_model=ResponseBool)
# async def retrieve_history_standard_part_relation(history_part_number: str, standard_part_number: str):
#     """
#     查询历史零件和标准零件的关系，若已绑定返回True，否则返回False。
#
#     - :return:
#     """
#     model = {}
#     try:
#         result = retrieve_mongo_all_values(
#             {
#                 "history_part_number": history_part_number,
#                 "standard_part_number": standard_part_number,
#             },
#             database_name=MONGO_DATABASE_NAME,
#             collection_name="02_04_relation",
#         )
#         if len(result) > 0:
#             model["data"] = True
#         else:
#             model["data"] = False
#
#         model["status"] = 1
#     except:
#
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.delete("/v1/history_standard_part_relation", response_model=ResponseDict)
# async def delete_history_standard_part_relation(queryModel: HistoryPartStandardPart):
#     """
#     取消绑定历史零件和标准零件
#
#     - :return:
#     """
#     model = {}
#     try:
#         model["data"] = {queryModel.history_part_number: queryModel.standard_part_number}
#         delete_mongo_value_by_filter_condition(
#             {
#                 "history_part_number": queryModel.history_part_number,
#                 "standard_part_number": queryModel.standard_part_number,
#             },
#             database_name=MONGO_DATABASE_NAME,
#             collection_name="02_04_relation",
#         )
#         model["status"] = 1
#     except:
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.post("/v1/standard_parameter_part_relation", response_model=ResponseDict)
# async def bind_standard_parameter_part(queryModel: StandardPartParameterModel):
#     """
#     绑定标准零件和参数化模型的编号
#
#     - :return:
#     """
#     model = {}
#     try:
#         create_one_mongo_value(
#             {
#                 "standard_part_number": queryModel.standard_part_number,
#                 "parameter_number": queryModel.parameter_number
#             },
#             database_name="do_center",
#             collection_name="04_05_relation",
#         )
#
#         model["status"] = 1
#         model["data"] = {queryModel.standard_part_number: queryModel.parameter_number}
#     except:
#
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.get("/v1/standard_parameter_part_relation", response_model=ResponseBool)
# async def retrieve_standard_parameter_part_relation(standard_part_number: str, parameter_number: str):
#     """
#     查询标准零件和参数化模型的关系，若已绑定返回True，否则返回False。
#
#     - :return:
#     """
#     model = {}
#     try:
#         result = retrieve_mongo_all_values(
#             {
#                 "standard_part_number": standard_part_number,
#                 "parameter_number": parameter_number
#             },
#             database_name="do_center",
#             collection_name="04_05_relation",
#         )
#         if len(result) > 0:
#             model["data"] = True
#         else:
#             model["data"] = False
#
#         model["status"] = 1
#     except:
#
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.delete("/v1/standard_parameter_part_relation", response_model=ResponseDict)
# async def delete_standard_parameter_part_relation(queryModel: StandardPartParameterModel):
#     """
#     取消绑定标准零件和参数化模型
#
#     - :return:
#     """
#     model = {}
#     try:
#         model["data"] = {queryModel.standard_part_number: queryModel.parameter_number}
#         delete_mongo_value_by_filter_condition(
#             {
#                 "standard_part_number": queryModel.standard_part_number,
#                 "parameter_number": queryModel.parameter_number,
#             },
#             database_name="do_center",
#             collection_name="04_05_relation",
#         )
#
#         model["status"] = 1
#     except:
#
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.post("/v1/history_parameter_part_relation", response_model=ResponseDict)
# async def bind_standard_parameter_part(queryModel: HistoryPartParameterModel):
#     """
#     绑定历史零件和参数化模型的编号
#
#     - :return:
#     """
#     model = {}
#     try:
#         create_one_mongo_value(
#             {
#                 "history_part_number": queryModel.history_part_number,
#                 "parameter_number": queryModel.parameter_number
#             },
#             database_name="do_center",
#             collection_name="02_05_relation",
#         )
#
#         model["status"] = 1
#         model["data"] = {queryModel.history_part_number: queryModel.parameter_number}
#     except:
#
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.get("/v1/history_parameter_part_relation", response_model=ResponseBool)
# async def retrieve_history_parameter_part_relation(history_part_number: str, parameter_number: str):
#     """
#     查询历史零件和参数化模型的关系，若已绑定返回True，否则返回False。
#
#     - :return:
#     """
#     model = {}
#     try:
#         result = retrieve_mongo_all_values(
#             {
#                 "history_part_number": history_part_number,
#                 "parameter_number": parameter_number
#             },
#             database_name="do_center",
#             collection_name="02_05_relation",
#         )
#         if len(result) > 0:
#             model["data"] = True
#         else:
#             model["data"] = False
#
#         model["status"] = 1
#     except:
#
#         model["status"] = 0
#     return model
#
#
# @parameter_model_router.delete("/v1/history_parameter_part_relation", response_model=ResponseDict)
# async def delete_history_parameter_part_relation(queryModel: HistoryPartParameterModel):
#     """
#     取消绑定历史零件和参数化模型
#     - :return:
#     """
#     model = {}
#     try:
#         model["data"] = {queryModel.history_part_number: queryModel.parameter_number}
#         delete_mongo_value_by_filter_condition(
#             {
#                 "history_part_number": queryModel.history_part_number,
#                 "parameter_number": queryModel.parameter_number,
#             },
#             database_name="do_center",
#             collection_name="02_05_relation",
#         )
#
#         model["status"] = 1
#     except:
#
#         model["status"] = 0
#     return model
#

@parameter_model_router.put("/v1/parameter_model_show")
async def change_size(queryModel: ParameterModelChangeSize):
    """
    关联中实时更改模型尺寸。首先会删除queryModel.number对应的原来的临时stl模型（如果有的话，这个模型是来自于之前对同一number的模型进行的操作而存在同一文件夹下），以免用户点击更新后看到错误尺寸的stl

    - :param queryModel:
    - :return:
    """
    # temp_stl_oss_address = f"DOCenter_Dev/Pythonfiles/temp/parameter_model/{queryModel.number}.glb"
    # print(delete_file_on_oss(temp_stl_oss_address))
    result = retrieve_all_mongo_values(
        filter_conditions={"number": queryModel.number},
        database_name=MONGO_DATABASE_NAME,
        collection_name=PARAMETER_MODEL_COLLECTION,
    )[0]

    result["file"]["tempArgs"] = [i.dict() for i in queryModel.args]

    # 发送去转化服务器的数据中，"file"里"tempArgs"的字段是这次添加的数据，且也已转化为字典了。
    data = requests.request(
        method="post",
        url=f"http://{TEMPORARY_CONVERT_MACHINE_URL}:{TEMPORARY_CONVERT_MACHINE_PORT}/parameter_model",
        # data=str(result, encoding="utf-8").encode('utf-8'),
        data=json.dumps(result)
    )

    model = {"data": data, "status": 1}
    return model
